package com.wenhai.concurrency.lock;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

/**
 * 这是个先进先出的锁，也就是只有队列的首元素可以获得锁
 *
 * @ClassName FIFOMutex
 * @Description
 * @Author 谢文海
 * @Date 2021/4/15 1:15
 * @Version 1.0
 **/
public class FIFOMutex {
    private final AtomicBoolean locked = new AtomicBoolean(false);
    private final Queue<Thread> waiters = new ConcurrentLinkedQueue<>();

    public void lock() {
        boolean wasInterrupted = false;
        Thread current = Thread.currentThread();
        waiters.add(current);
        // 如果当前队首不是当前线程获取当前锁已经被其他线程获取就挂起自己
        while (waiters.peek() != current || !locked.compareAndSet(false, true)) {
            LockSupport.park(this);
            // 中断标记
            if (Thread.interrupted()) {
                wasInterrupted = true;
            }
        }
        // 加锁成功或者队列对首是当前线程移除
        waiters.remove();
        if (wasInterrupted) {
            current.interrupt();
        }
    }

    public void unlock (){
        locked.set(false);
        LockSupport.unpark(waiters.peek());
    }
}
